#include "pch.h"
#include "Explosion.h"
#include "Random.h"

std::unique_ptr<dxroids::GameObject> dxroids::Explosion::NewDefault(Vector const & _pos)
{
   auto p = std::unique_ptr<GameObject>(new Explosion(_pos, DXROIDS_EXPLOSION_MAX_RADIUS));
   p->Initialize(dxroids::GetDirect2DFactory());
   p->SetIsActive(true);
   return std::move(p);
}

dxroids::Explosion::Explosion(Vector const & _pos, float _max_radius)
   : GameObject(_pos, DXROIDS_EXPLOSTION_DIAMETER)
   , max_radius_(_max_radius)
   , frame_count_(std::numeric_limits<int>::max())
{
   float rotate = 0.0f;
   float const radius_squared = (max_radius_ * max_radius_);

   Random rand;

   particles_.reserve(DXROIDS_EXPLOSION_NUM_POINTS);
   particles_.resize(DXROIDS_EXPLOSION_NUM_POINTS);

   for (size_t i = 0; i < particles_.size(); ++i)
   {      
      float const v = (rand.NextFloat() + 1.0f) * DXROIDS_EXPLOSION_PARTICLE_VELOCITY;
      float const r = rand.NextFloat(DXROIDS_EXPLOSION_PARTICLE_JITTER_MIN, DXROIDS_EXPLOSION_PARTICLE_JITTER_MIN);

      Vector velocity(static_cast<float>(-v), 0.0f);
      velocity.Rotate(DegreesToRadians(rotate * static_cast<float>(r)));
      
      std::unique_ptr<Particle> p(new Particle(_pos, velocity, max_radius_));
      p->SetIsActive(true);

      int const n = static_cast<int>(ceilf(v / velocity.MagnitudeSquared()));
      if (n < frame_count_)
      {
         frame_count_ = n;
      }

      rotate += 360.0f / DXROIDS_EXPLOSION_NUM_POINTS;
      particles_[i] = std::move(p);      
   }   
}

dxroids::Explosion::~Explosion()
{
   particles_.clear();
}

DXROIDS_COM_PTR<ID2D1Geometry> dxroids::Explosion::CreateGeometry(DXROIDS_COM_PTR<ID2D1Factory> const & _factory,
         float _scale)
{
   for (std::unique_ptr<Particle> const & p : particles_)
   {
      p->Initialize(_factory);
   }
   return nullptr;
}

void dxroids::Explosion::Render(RenderContext const & _ctx)
{
   for (std::unique_ptr<Particle> const & p : particles_)
   {
      p->Render(_ctx);
   }
}


void dxroids::Explosion::UpdateFrame(
   GameTime const & _timer, 
   ClippingInformation const & _clip, 
   bool * _wrap_horizontal, 
   bool * _wrap_vertical)
{
   bool any_active = false;
   for (std::unique_ptr<Particle> const & p : particles_) 
   {
      p->UpdateFrame(_timer, _clip, nullptr, nullptr);
      if (p->IsActive())
      {
         any_active = true;
      }
   }

   if (!any_active)
   {
      SetIsActive(false);
   }

   if (_wrap_horizontal)
   {
      *_wrap_horizontal = false;
   }
   if (_wrap_vertical)
   {
      *_wrap_vertical = false;
   }
}

